package cn.com.bluemoon.daps.system.service.impl;

import cn.com.bluemoon.daps.api.model.RemoteDataModelService;
import cn.com.bluemoon.daps.common.constant.DapConstant;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.common.enums.SystemType;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.model.entity.DapDataModel;
import cn.com.bluemoon.daps.system.dto.SysInfoDto;
import cn.com.bluemoon.daps.system.dto.SystemInfoDto;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasource;
import cn.com.bluemoon.daps.system.entity.DapSystemInfo;
import cn.com.bluemoon.daps.system.entity.DapSystemLeader;
import cn.com.bluemoon.daps.system.mapper.DapSystemInfoMapper;
import cn.com.bluemoon.daps.system.mapper.DapSystemLeaderMapper;
import cn.com.bluemoon.daps.system.service.DapSystemBizLineService;
import cn.com.bluemoon.daps.system.service.DapSystemDatasourceService;
import cn.com.bluemoon.daps.system.service.DapSystemInfoService;
import cn.com.bluemoon.daps.system.service.DapSystemLeaderService;
import cn.com.bluemoon.daps.system.vo.SimpleSysInfoVo;
import cn.com.bluemoon.daps.system.vo.SystemInfoVo;
import cn.com.bluemoon.datasecurity.app.sdk.RemoteDataSecurityApproveService;
import cn.com.bluemoon.datasecurity.app.sdk.RemoteMetaDataTableExtService;
import cn.com.bluemoon.metadata.inter.RemoteMetaDataTableService;
import cn.com.bluemoon.metadata.sync.inter.SystemSyncService;
import cn.com.bluemoon.metadata.sync.inter.dto.in.SystemSyncRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableSet;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 系统表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-08-03
 */
@Slf4j
@Service
@Transactional
public class DapSystemInfoServiceImpl extends ServiceImpl<DapSystemInfoMapper, DapSystemInfo> implements DapSystemInfoService {

    @Resource
    DapSystemInfoMapper dapSystemInfoMapper;

    @Resource
    DapSystemLeaderMapper dapSystemLeaderMapper;

    @Resource
    RemoteDataModelService dapDataModelService;

    @Resource
    DapSystemDatasourceService dapSystemDatasourceService;

    @Resource
    DapSystemLeaderService dapSystemLeaderService;

//    @Resource
//    SystemSyncService systemSyncService;

    @Resource
    DapSystemBizLineService dapSystemBizLineService;

    @Resource
    RemoteMetaDataTableService remoteMetaDataTableService;

    @Resource
    RemoteMetaDataTableExtService remoteMetaDataTableExtService;

    @Resource
    RemoteDataSecurityApproveService remoteDataSecurityApproveService;

    @Override
    public IPage<SystemInfoDto> getSysPageList(Integer pageSize, Integer pageNum, String sysName) {

        // 分页条件
        Page<DapSystemInfo> pages = new Page<>(pageNum, pageSize);
        // 结果集
        IPage<DapSystemInfo> pageList;
        if (StringUtils.isEmpty(sysName)) {
            // 不带数据源名称的分页查询
            pageList = dapSystemInfoMapper.selectPage(pages, new LambdaQueryWrapper<DapSystemInfo>()
                    .eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode())
                    .orderByDesc(DapSystemInfo::getUpdateTime, DapSystemInfo::getCreateTime));
        } else {
            // 带数据源的模糊分页查询
            pageList = dapSystemInfoMapper.selectByName(pages, sysName, BmStatus.ON.getCode());

        }
        // 查询系统相关负责人
        List<SystemInfoDto> list = new ArrayList<>();
        for (DapSystemInfo dapSystemInfo : pageList.getRecords()) {
            SystemInfoDto systemInfoDto = new SystemInfoDto();
            // 获取创建人信息
            DapSystemLeader dapSystemLeader = dapSystemLeaderMapper
                    .selectOne(new LambdaQueryWrapper<DapSystemLeader>()
                            .eq(DapSystemLeader::getSystemId, dapSystemInfo.getId()));
            // 重新组装数据
            systemInfoDto.setDapSystemInfo(dapSystemInfo);
            systemInfoDto.setDapSystemLeader(dapSystemLeader);
            // 封装进list集合
            list.add(systemInfoDto);
        }
        // 重新组装分页条件
        IPage<SystemInfoDto> infoDtoPage = new Page<>();
        infoDtoPage.setRecords(list);
        infoDtoPage.setSize(pageList.getSize());
        infoDtoPage.setCurrent(pageList.getCurrent());
        infoDtoPage.setPages(pageList.getPages());
        infoDtoPage.setTotal(pageList.getTotal());
        return infoDtoPage;
    }

    /**
     * 新增系统，返回id值
     */
    @Override
    @Transactional(rollbackFor = {DapException.class, Exception.class})
    public ResultBean<Boolean> insertSystem(SystemInfoVo systemInfoVo) {

        // 查询系统名称或系统简称是否重复
        List<DapSystemInfo> list = dapSystemInfoMapper.selectList(new LambdaQueryWrapper<DapSystemInfo>()
                .eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode())
                .and(qw -> qw.eq(DapSystemInfo::getNameShorter, systemInfoVo.getNameShorter())
                        .or().eq(DapSystemInfo::getName, systemInfoVo.getSysName())));

        if (!list.isEmpty()) {
            return ResultBean.error("系统名或系统简称重复！");
        }
        // 新增系统
        DapSystemInfo dapSystemInfo = new DapSystemInfo();
        BeanUtils.copyProperties(systemInfoVo, dapSystemInfo);
        dapSystemInfo.setName(systemInfoVo.getSysName());
        dapSystemInfo.setType(systemInfoVo.getSysType());
        boolean save = this.save(dapSystemInfo);
        // 新增系统相关负责人表
        DapSystemLeader dapSystemLeader = new DapSystemLeader();
        BeanUtils.copyProperties(systemInfoVo, dapSystemLeader);
        dapSystemLeader.setSystemId(dapSystemInfo.getId());
        dapSystemLeaderService.getBaseMapper().insert(dapSystemLeader);
        // 新增元数据数据源
        if (save) {
            SystemSyncRequest systemSyncRequest = new SystemSyncRequest();
            systemSyncRequest.setCreateDate(new Date());
            systemSyncRequest.setSystemName(systemInfoVo.getSysName());
            systemSyncRequest.setUpdateDate(new Date());
            systemSyncRequest.setSystemId(dapSystemInfo.getId());
            systemSyncRequest.setComment(systemInfoVo.getDescription());
//            cn.com.bluemoon.metadata.common.ResultBean resultBean = systemSyncService.addSystem(systemSyncRequest);
//            if (resultBean.getCode() != 200) {
//                throw new DapException(resultBean.getMsg());
//            }
        }
        // 添加数据源引用关系
        List<String> ids = systemInfoVo.getIds();
        for (String id : ids) {
            dapSystemDatasourceService.getBaseMapper().update(null, new LambdaUpdateWrapper<DapSystemDatasource>()
                    .eq(DapSystemDatasource::getId, id).set(DapSystemDatasource::getSystemInfoId, dapSystemInfo.getId()));
        }
        return ResultBean.ok(true);
    }

    /**
     * 根据id获得系统信息
     */
    @Override
    public DapSystemInfo getSysById(String id) {

        DapSystemInfo dapSystemInfo = dapSystemInfoMapper.selectOne(new QueryWrapper<DapSystemInfo>().eq("id", id));
        return dapSystemInfo;
    }

    /**
     * 删除系统，可批量 通过服务调接口
     */
    @Override
    @Transactional(rollbackFor = {DapException.class, Exception.class})
    public ResultBean<Boolean> deleteSystem(List<DapSystemInfo> list) {

        Boolean isDel = true;
        StringBuffer stringBuffer = new StringBuffer();
        List<DapSystemInfo> sysInfo = new ArrayList<>();
        for (DapSystemInfo systemInfo : list) {
            // 查询系统是否被引用
            DapSystemInfo dapSystemInfo = new DapSystemInfo();
            dapSystemInfo.setId(systemInfo.getId());
            dapSystemInfo.setBmStatus(BmStatus.DELETE);
            sysInfo.add(dapSystemInfo);
        }
        if (isDel) {
            // 将系统信息置为删除状态
            List<SystemSyncRequest> ids = new ArrayList<>();
            list.forEach(systemInfo -> {
                SystemSyncRequest systemSyncRequest = new SystemSyncRequest();
                systemSyncRequest.setSystemId(systemInfo.getId());
                systemSyncRequest.setSystemName(systemInfo.getName());
                systemSyncRequest.setUpdateDate(new Date());
                ids.add(systemSyncRequest);
            });
//            cn.com.bluemoon.metadata.common.ResultBean resultBean = systemSyncService.deleteSystem(ids);
            // 如果元数据模块删除成功，则进行删除系统
//            if (resultBean.getCode() == 200) {
                boolean b = this.updateBatchById(sysInfo);
                // 将引用的数据源中的系统id置空
                for (DapSystemInfo dapSystemInfo : list) {
                    dapSystemDatasourceService.update(new LambdaUpdateWrapper<DapSystemDatasource>()
                            .set(DapSystemDatasource::getSystemInfoId, "0")
                            .eq(DapSystemDatasource::getSystemInfoId, dapSystemInfo.getId())
                            .eq(DapSystemDatasource::getBmStatus, BmStatus.ON.getCode()));
                    // 删除系统配置的管理人员
                    if(dapSystemInfo.getBizLineId() != null){
                        dapSystemBizLineService.deleteBizLineDetailByBizLineIdAndSystemId(null, dapSystemInfo.getId());
                    }
                }
                return ResultBean.ok(b);
//            } else {
//                return ResultBean.error(resultBean.getMsg());
//            }
        } else {
            return ResultBean.error(stringBuffer + "系统被引用无法删除");
        }
    }

    /**
     * 通过系统id获得详情
     */
    @Override
    public SysInfoDto getSysInfo(String id) {

        SysInfoDto sysInfoDto = dapSystemInfoMapper.selectSysInfo(id, BmStatus.ON.getCode());
        return sysInfoDto;
    }

    /**
     * 系统更新
     */
    @Override
    @Transactional(rollbackFor = {DapException.class, Exception.class})
    public ResultBean<Boolean> updateSystem(SystemInfoVo systemInfoVo) {

        // 查询系统名称或系统简称是否重复
        List<DapSystemInfo> dapSystemInfo = dapSystemInfoMapper.selectList(new LambdaQueryWrapper<DapSystemInfo>()
                .eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode())
                .and(i -> i.eq(DapSystemInfo::getNameShorter, systemInfoVo.getNameShorter())
                        .or().eq(DapSystemInfo::getName, systemInfoVo.getSysName()))
                .ne(DapSystemInfo::getId, systemInfoVo.getSystemId()));
        boolean isModify = (dapSystemInfo.isEmpty()) ? true : false;
        // 进行编辑
        if (isModify) {
            // 查询之前的系统信息
            DapSystemInfo info = dapSystemInfoMapper.selectById(systemInfoVo.getSystemId());
            // 编辑系统
            DapSystemInfo systemInfo = new DapSystemInfo();
            BeanUtils.copyProperties(systemInfoVo, systemInfo);
            systemInfo.setName(systemInfoVo.getSysName());
            systemInfo.setType(systemInfoVo.getSysType());
            systemInfo.setId(systemInfoVo.getSystemId());
            // 数据安全模块
            if(info.getBizLineId() != null && info.getBizLineId() != systemInfoVo.getBizLineId()){
                try {
                    cn.com.bluemoon.metadata.common.ResultBean<Boolean> resultBean = remoteDataSecurityApproveService.isApprovingBySystemId(systemInfoVo.getSystemId());
                    if(resultBean.getCode() == 200 && !resultBean.getContent()){
                        // 删除业务线与系统的管理
                        dapSystemBizLineService.deleteBizLineDetailByBizLineIdAndSystemId(info.getBizLineId(), info.getId());
                        if(!systemInfoVo.getSysType().equals(SystemType.WAREHOUSE_SYS)){
                            // 刷新图库
                            remoteMetaDataTableService.syncTableBizLineIdBySystemId(systemInfoVo.getSystemId(), systemInfoVo.getBizLineId());
                            // 刷新mysql
                            remoteMetaDataTableExtService.syncTableBizLineIdBySystemId(systemInfoVo.getSystemId(), systemInfoVo.getBizLineId());
                        }
                    }else {
                        return ResultBean.error(resultBean.getContent() ? "当前系统数据安全模块存在审批数据，不可更改业务线" : resultBean.getMsg());
                    }
                }catch (DapException e){
                    log.info(e.getMessage(), e);
                }
            }
            dapSystemInfoMapper.updateById(systemInfo);
            // 更新元数据模块
            SystemSyncRequest systemSyncRequest = new SystemSyncRequest();
            systemSyncRequest.setSystemName(systemInfoVo.getSysName());
            systemSyncRequest.setUpdateDate(new Date());
            systemSyncRequest.setSystemId(systemInfoVo.getSystemId());
            systemSyncRequest.setComment(systemInfoVo.getDescription());
//            cn.com.bluemoon.metadata.common.ResultBean resultBean = systemSyncService.updateSystem(systemSyncRequest);
//            if (resultBean.getCode() != 200) {
//                throw new DapException(resultBean.getMsg());
//            }
            // 更新系统相关负责人表
            DapSystemLeader dapSystemLeader = new DapSystemLeader();
            BeanUtils.copyProperties(systemInfoVo, dapSystemLeader);
            dapSystemLeader.setId(systemInfoVo.getLeaderId());
            dapSystemLeaderService.updateById(dapSystemLeader);
            // 获得到引用的数据源
            List<String> ids = systemInfoVo.getIds();
            // 先将该系统引用的数据源置空
            dapSystemDatasourceService.update(new LambdaUpdateWrapper<DapSystemDatasource>()
                    .set(DapSystemDatasource::getSystemInfoId, "0")
                    .eq(DapSystemDatasource::getSystemInfoId, systemInfoVo.getSystemId()));
            // 再引用的新的数据源
            for (String id : ids) {
                dapSystemDatasourceService.getBaseMapper().update(null, new LambdaUpdateWrapper<DapSystemDatasource>()
                        .eq(DapSystemDatasource::getId, id).set(DapSystemDatasource::getSystemInfoId, systemInfoVo.getSystemId()));
            }
            return ResultBean.ok(true);
        } else {
            return ResultBean.error("系统名或系统简称重复！");
        }

    }

    @Override
    @Cacheable(keyGenerator = DapConstant.CACHE_KEY_GENERATOR, cacheNames = DapConstant.DapSystem.CACHE_NAME)
    public Optional<DapSystemInfo> getCacheOneById(String sysId) {
        return Optional.ofNullable(getById(sysId));
    }

    /**
     * 根据员工号+用户类型相关系统信息
     * 用户类型对应系统人员列表：1 产品负责人、2技术负责人、3业务负责人
     * {@link DapSystemLeader#getProId()}
     * {@link DapSystemLeader#getTecId()}
     * {@link DapSystemLeader#getBusId()}
     *
     * @param userId   用户工号
     * @param userType 用户类型对应系统人员列表：1 产品负责人、2技术负责人、3业务负责人，非必填，默认为2
     * @return 根据员工号+用户类型相关系统信息
     */
    @Override
    public List<SystemInfoDto> getSystemInfosByUserIdAndType(String userId, Integer userType) {
        if (StringUtils.isBlank(userId)) {
            return Collections.emptyList();
        }
        if (userType == null) {
            userType = 2;
        }
        ImmutableSet<Integer> validTypes = ImmutableSet.of(1, 2, 3);
        BmAssetUtils.isTrue(validTypes.contains(userType), "只支持获取人员类型有：1 产品负责人、2技术负责人、3业务负责人");
        List<SystemInfoDto> res = dapSystemInfoMapper.selectMapsByParam(userId, userType);
        return res;
    }

    @Override
    public List<SimpleSysInfoVo> listByDbType(Integer dbType) {
        // predicate
        if (dbType == null) return Collections.emptyList();
        Arrays.stream(DatabaseType.values()).filter(d -> d.getCode() == dbType).findFirst()
                .orElseThrow(() -> new DapThrowException("系统不支持获取该数据库类型[dbType=" + dbType + "]相关系统列表"));
        // result
        List<SimpleSysInfoVo> sysInfoVos = getBaseMapper().selectListByDbType(dbType);
        return sysInfoVos;
    }

    @Override
    public List<DapSystemInfo> findByBizLineId(Integer bizLineId) {
        LambdaQueryWrapper<DapSystemInfo> eq = bmLambdaQuery()
                .and(wrapper ->
                        wrapper.eq(DapSystemInfo::getBizLineId, bizLineId)
                                .or()
                                .eq(DapSystemInfo::getType, SystemType.WAREHOUSE_SYS)
                );
        return list(eq);
    }

    @Override
    public List<DapSystemInfo> relatedBizLineId(Integer bizLineId) {
        LambdaQueryWrapper<DapSystemInfo> eq = bmLambdaQuery()
                .and(wrapper ->
                        wrapper.eq(DapSystemInfo::getBizLineId, bizLineId)
                );
        return list(eq);
    }
}
